package com.apes.fn.scm.retailOrder.service.account.retail;

import com.alibaba.fastjson.JSONObject;
import com.apes.crm.business.model.InsuranceCompanyDetail;
import com.apes.fn.business.fixedLoss.modle.LossQuotation;
import com.apes.fn.business.fixedLoss.repository.LossQuotationRepository;
import com.apes.fn.business.fixedLoss.service.FixedLossToForeign;
import com.apes.fn.scm.insuranceRules.InsuranceRule;
import com.apes.fn.scm.insuranceRules.InsuranceRuleService;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.service.account.BackBatchAndSupplierService;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.scm.retailOrder.service.expense.InsuranceCrossDiscount;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 跨公司委托定损
 *
 * @Author wuq
 * @Date 2021-10-9
 */
@RetailAccount(value = "insuranceDiscountCross", name = "跨公司委托定损")
@Service
public class InsuranceDiscountCrossVoucherService extends BackBatchAndSupplierService {

    @Autowired
    private TaxService taxService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;


    public void process(RetailAccountData retailAccountData) {
        RetailOrder retailOrder = retailAccountData.getRetailOrder();

        InsuranceRule insuranceRule = SpringManager.getBean(InsuranceRuleService.class)
                .findByDeptAndInsuranceCompany(retailOrder.getServiceDept(), retailOrder.getInsuranceCompany());
        if (Objects.isNull(insuranceRule)) throw new RuntimeException("没有找到对应的车型规则,，部门："+ retailOrder.getServiceDept().getId() + "，保险公司："+ retailOrder.getInsuranceCompany().getId());
        if (!retailOrder.getServiceDept().getCompany().getId().equals(insuranceRule.getCompany().getId())) throw new RuntimeException("跨公司委托定损基地不能对保险公司开票！");

        /** 生成基地对保险公司的分销单 **/
        createInsuranceSale(retailOrder);
    }



    /**
     * 基地凭证处理
     * 基地找门店采购，然后全额卖给保险公司
     *
     * @param retailOrder 门店零售单
     * @return RetailOrder
     */
    private RetailOrder createInsuranceSale(RetailOrder retailOrder) {
        // 基地采购凭证、账单
        Voucher purchaseVoucher = createPurchaseVoucher(retailOrder);

        // 基地销售凭证、账单
        createSaleVoucher(retailOrder, purchaseVoucher);
        return retailOrder;
    }

    /**
     * 创建基地对门店的采购凭证
     *
     * @param retailOrder 门店零售单
     * @return Voucher
     */
    private Voucher createPurchaseVoucher(RetailOrder retailOrder) {
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.PURCHASE_ORDER);

        voucher.setClerk(retailOrder.getClerk()); //业务员
        voucher.setScene(retailOrder.getScene());
        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        voucher.setSource(retailOrder.getId());
        voucher.setSourceBusinessType(retailOrder.getInnerBusinessType());

        Dept serviceDept = retailOrder.getServiceDept();
        voucher.setDept(serviceDept);
        voucher.setCompany(serviceDept.getCompany());
        voucher.setPartner(retailOrder.getCompany().getParty().getPatyRoleByType("Supplier"));

        // 查询零售单的销售凭证，作为来源
        List<Voucher> saleVouchers = SpringManager.getBean(VoucherRepository.class)
                .findAll(JpaDsl.toCriteriaByEq("source", retailOrder.getId(), "origin", retailOrder.getId(), "businessType", BusinessType.SALE_ORDER));
        if (saleVouchers.isEmpty()) throw new RuntimeException("基地创建采购凭证时,没有找到源单据的销售凭证, 来源单号：" + retailOrder.getId());
        if (saleVouchers.size() > 1) throw new RuntimeException("基地创建采购凭证时,找到多个销售凭证, 来源单号：" + retailOrder.getId());
        voucher.setSource(saleVouchers.get(0).getId());
        voucher.setSourceBusinessType(saleVouchers.get(0).getInnerBusinessType());
        voucher.setClassification(VoucherType.ENTRUST_LOSS);
        voucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());

        Contract contract = contractService.getContract(serviceDept, retailOrder.getCompany(), "distribution", "supplier", "跨公司委托定损业务");
        voucher.setContract(contract);
        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式

        // 获取基地分红比例参数
        LossQuotation lossQuotation = SpringManager.getBean(LossQuotationRepository.class).findOne(retailOrder.getSource());
        double ratio = lossQuotation.getDividendStore();

        PartyRole supplier = voucher.getPartner();
        voucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        retailOrderItem -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(retailOrderItem, voucherItem, "product", "uom");

                            voucherItem.setProductQty(retailOrderItem.getProductUomQty());
                            voucherItem.setOriginItemId(retailOrderItem.getId());
                            voucherItem.setSourceItemId(retailOrderItem.getId());
                            voucherItem.setDiscount(retailOrderItem.getDiscountAmount());

                            voucherItem.setOwner(retailOrder.getServiceDept().getCompany());

                            Tax tax = taxService.getPurchaseTax(retailOrder.getServiceDept().getCompany(), supplier, retailOrderItem.getProduct());   //供应商进项税
                            voucherItem.setTax(tax);

                            // 计算比例对应的单价以及金额
                            voucherItem.setPriceUnit(Arith.round(retailOrderItem.getPriceUnit() * ratio, 4));
                            return voucherItem;
                        }).collect(Collectors.toSet())
        );

        // 创建账单
        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        changeFrostQty(voucher, "委托定损流程，基地对门店采购时生成");

        //增加账单
        createInvoiceAndFixOriginNumber(retailOrder, voucher);
        return voucher;
    }


    /**
     * 创建基地对保险公司的销售凭证
     *
     * @param retailOrder
     */
    private void createSaleVoucher(RetailOrder retailOrder, Voucher purchaseVoucher) {
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);

        ReflectUtil.copy(purchaseVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        voucher.setClerk(retailOrder.getClerk()); //业务员
        voucher.setScene(retailOrder.getScene());
        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        voucher.setSource(purchaseVoucher.getId());      // 来源为采购凭证
        voucher.setSourceBusinessType(purchaseVoucher.getInnerBusinessType());

        // 通过保险公司明细找保险公司客户
        InsuranceCompanyDetail companyDetail = SpringManager.getBean(FixedLossToForeign.class)
                .getInsuranceCompanyToClient(retailOrder.getInsuranceCompany(), retailOrder.getServiceDept());
        voucher.setPartner( companyDetail.getClient() );

        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "customer", "跨公司委托定损");
        voucher.setContract(contract);
        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式
        voucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());
        voucher.setClassification(VoucherType.ENTRUST_LOSS_BASE_SALE);    // 委托定损基地对保险公司销售

        // 获取平台分红比例参数
        LossQuotation lossQuotation = SpringManager.getBean(LossQuotationRepository.class).findOne(retailOrder.getSource());
        double ratio = lossQuotation.getDividendPlatform();

        voucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        retailOrderItem -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(retailOrderItem, voucherItem, "product", "uom", "tax");

                            voucherItem.setProductQty(retailOrderItem.getProductUomQty());
                            voucherItem.setPriceUnit(retailOrderItem.getPriceUnit());      // 默认为零售单价
                            voucherItem.setOriginItemId(retailOrderItem.getId());
                            voucherItem.setSourceItemId(retailOrderItem.getId());
                            voucherItem.setDiscount(retailOrderItem.getDiscountAmount());

                            Tax tax = taxService.getSaleTax(purchaseVoucher.getCompany(), retailOrderItem.getProduct());
                            voucherItem.setTax(tax);

                            voucherItem.setOwner(retailOrder.getServiceDept().getCompany());
                            voucherItem.setLossQuotationFee(Arith.round(retailOrderItem.getPriceTotal() * ratio, 4));
                            if (voucherItem.getLossQuotationFee() > 0) {
                                //生成平台定损费用
                                retailOrder.setAmtTotal(voucherItem.getLossQuotationFee());
                                InsuranceCrossDiscount insuranceCrossDiscount = new InsuranceCrossDiscount(retailOrder);
                                insuranceCrossDiscount.create(new JSONObject());
                            }
                            return voucherItem;
                        }).collect(Collectors.toSet())
        );
        double lossQuotationFeeAmt = voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getLossQuotationFee).sum();
        voucher.setLossQuotationFeeAmt(lossQuotationFeeAmt);

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            purchaseVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        // 创建账单
        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        //增加账单
        createInvoiceAndFixOriginNumber(retailOrder, voucher);
    }

}
